package models;

import java.util.Arrays;

public class Hand {

    public static int HAND_SIZE = 4;
    private static int LACK_OF_CARD = -1;
    private int[] hand = new int[HAND_SIZE];
    static int i = 1;

    Hand(Deck2 deck, int playerNumber) {

	for (int i = 0; i < HAND_SIZE; i++) {
	    hand[i] = Hand.LACK_OF_CARD;
	}
	for (int i = 0; i < HAND_SIZE; i++) {
	    try {
		drawCard(deck, playerNumber);
	    } catch (Exception e) {
		System.out.println(e.getMessage());
		System.out.println("Coś tu nie gra");
	    }
	}
    }

    public static String getReducedHandCardSet(int[] hand) {
	int[] reducedHand = getReducedHand(hand);
	String cardSet = "";
	for (int i = 0; i < hand.length; i++) {
	    boolean elementInReducedHand = false;
	    for (int j = 0; j < reducedHand.length; j++) {
		if (reducedHand[j] == hand[i])
		    elementInReducedHand = true;
	    }
	    if (elementInReducedHand) {
		cardSet += "1";
	    } else {
		cardSet += "0";
	    }
	}
	return cardSet;
    }

    public static int[] getReducedHand(int[] hand) {
	// System.out.println(i++);
	int[][][] collisionMatrix = new int[hand.length][hand.length][];
	boolean collisionExist = false;
	for (int i = 0; i < hand.length; i++) {
	    for (int j = 0; j < hand.length; j++) {
		if ((i != j)
			&& (hand[i] / 13 == hand[j] / 13 || hand[i] % 13 == hand[j] % 13)) {
		    collisionExist = true;
		    int[] reducedHandCandidate = new int[hand.length - 1];
		    for (int k = 0; k < reducedHandCandidate.length; k++) {
			if (k < i)
			    reducedHandCandidate[k] = hand[k];
			else
			    reducedHandCandidate[k] = hand[k + 1];
		    }
		    collisionMatrix[i][j] = getReducedHand(reducedHandCandidate);
		} else
		    collisionMatrix[i][j] = new int[] { -2, -2, -2, -2 };
	    }
	}
	if (collisionExist) {
	    int[] bestHand = new int[] { -1, -1, -1, -1 };
	    for (int i = 0; i < hand.length; i++) {
		for (int j = 0; j < hand.length; j++) {
		    if (!Arrays.equals(collisionMatrix[i][j], new int[] { -2,
			    -2, -2, -2 }))
			if (Arrays.equals(bestHand,
				new int[] { -1, -1, -1, -1 }))
			    bestHand = collisionMatrix[i][j];
			else {
			    bestHand = giveBetterHand(bestHand,
				    collisionMatrix[i][j]);
			}
		}
	    }
	    return bestHand;
	} else
	    return hand;
    }

    public static int[] giveBetterHand(int[] handOne, int[] handTwo) { // if
								       // equal
								       // returns
								       // handOne
	if (handOne.length > handTwo.length)
	    return handOne;
	if (handOne.length < handTwo.length)
	    return handTwo;
	int[] cardsFromOne = new int[handOne.length];
	int[] cardsFromTwo = new int[handTwo.length];
	for (int i = 0; i < handOne.length; i++) {
	    cardsFromOne[i] = handOne[i] % 13;
	    cardsFromTwo[i] = handTwo[i] % 13;
	}
	Arrays.sort(cardsFromOne);
	Arrays.sort(cardsFromTwo);
	for (int i = handOne.length - 1; i >= 0; i--) {
	    if (cardsFromOne[i] < cardsFromTwo[i])
		return handOne;
	    if (cardsFromOne[i] > cardsFromTwo[i])
		return handTwo;
	}
	return handOne;
    }

    public static int giveWorstCard(int[] hand) {
	for (int i = 0; i < hand.length; i++) {
	    hand[i] = hand[i] % 13; // want just Rank;
	}
	Arrays.sort(hand);
	return hand[hand.length - 1];
    }

    public void drawCard(Deck2 deck, int playerNumber) {
	int i = 0;
	while (hand[i] != Hand.LACK_OF_CARD) {
	    i++;
	}
	hand[i] = deck.giveCard(playerNumber);
    }

    public void drawAllCards(Deck2 deck, int playerNumber) {
	for (int i = 0; i < HAND_SIZE; i++) {
	    hand[i] = deck.giveCard(playerNumber);
	}
    }

    /*
     * cardSet is binary representation of cards player want to discard e.g. we
     * have cards: A|B|C|D and want to discard B then cardSet := 0100(2) = 4 if
     * we want to discard A and C the cardSet will be 1001(2) = 9
     */
    public int[] discardCards(Deck2 deck, int cardSet) {
	int[] discardedCards = new int[Integer.bitCount(cardSet)]; // Number of
	System.out.println("discardedCards:" + discardedCards.length);

	for (int i = HAND_SIZE - 1; i >= 0; i--) {
	    if (cardSet % 2 == 1) {
		for (int j = 0; j < discardedCards.length; j++) {
		    if (discardedCards[j] != 0)
			discardedCards[j] = hand[i];
		}
		deck.returnCardToDeck2(hand[i]);
		hand[i] = -1;
	    }
	    cardSet /= 2;
	}
	return discardedCards;
    }

    public void discardAllCards(Deck2 deck) {
	for (int i = HAND_SIZE - 1; i >= 0; i--) {
	    if (hand[i] != -1) {
		deck.returnCardToDeck2(hand[i]);
		hand[i] = -1;
	    }
	}
    }

    public void changeCards(Deck2 deck, int playerNumber, int cardSet) {
	int[] discardedCards = discardCards(deck, cardSet);
	for (int i = 0; i < discardedCards.length; i++) {
	    try {
		this.drawCard(deck, playerNumber);
	    } catch (Exception e) {
		e.getMessage();
	    }
	}
    }

    public int[] getCards() {
	return hand;
    }

    public void setCards(int[] cards) {
	hand = cards;
    }

    public String getString() {
	String s = "";
	for (int i = 0; i < HAND_SIZE; i++) {
	    s = s + getOneCard(i);
	}
	return s;
    }

    /**
     * return "00","01"...."09"..."51"
     * 
     * @param index
     * @return
     */
    public String getOneCard(int index) {
	if (hand[index] < 10) {
	    return ("0" + Integer.toString(hand[index]));
	} else {
	    return Integer.toString(hand[index]);
	}
    }

    public String getFormatedString() {
	String s = "";
	for( int i=0; i< HAND_SIZE; i++) {
	    s = s + Deck2.giveFullName(hand[i]) + ", "; 
	}
	return s;
    }
}